﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OfficeClip.OpenSource.StyleFix.Drivers;
using OfficeClip.OpenSource.StyleFix;
using System.Collections.Generic;

namespace StyleFixUnitTest
{
    [TestClass]
    public class LayoutRulesTest
    {
        private TestContext testContextInstance;
        private LayoutRules target;
        private SAObject saObject;
        private List<SAObject> saObjects;

        public LayoutRulesTest()
        {
            target = new LayoutRules(); 
            target.ForceAllow = true;
            saObject = new SAObject(string.Empty, 1, 1, string.Empty, false);
        }
        /// <summry>
        /// A test for SA1503_CurlyBracketsMustNotBeOmitted
        /// </summry>
        [TestMethod()]
        public void SA1503_CurlyBracketsMustNotBeOmittedTest()
        {
            List<SFWorkingLine> workingLines = new List<SFWorkingLine>();
            saObjects = new List<SAObject>();
            saObject.ErrorId = "SA1503";
            saObject.Description = "The body of the if statement must be wrapped";
            saObjects.Add(saObject);
            List<SAObject> noViolations = new List<SAObject>();
            //case 1
            SFWorkingLine workingLine = new SFWorkingLine(1, "\tif (true) check();", false, saObjects);
            workingLines.Add(workingLine);
            //case 2
            workingLine = new SFWorkingLine(2, "\tif (true)", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(3, "\t\tcheck();", false, saObjects);
            workingLines.Add(workingLine);
            //case 3
            workingLine = new SFWorkingLine(4, "\tif (something &&", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(4, "\t    somethingelse)", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(5, "\t\tthrow new Exception(String.Format(", false, saObjects);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(6, "\t\t\"{0}\", example));", false, noViolations);
            workingLines.Add(workingLine);
            List<SFWorkingLine> workingLinesExpected = new List<SFWorkingLine>();
            //case 1
            SFWorkingLine workingLineExpected = new SFWorkingLine(1, "\tif (true)", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(2, "\t{", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(3, "\t    check();", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(4, "\t}", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            //case 2
            workingLineExpected = new SFWorkingLine(1, "\tif (true)", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(2, "\t{", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(3, "\t\tcheck();", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(4, "\t}", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            //case 3
            workingLineExpected = new SFWorkingLine(1, "\tif (something &&", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(1, "\t    somethingelse)", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(2, "\t{", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(3, "\t\tthrow new Exception(String.Format(", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(4, "\t\t\"{0}\", example));", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(5, "\t}", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            target.SA1503_CurlyBracketsMustNotBeOmittedTest(ref workingLines);
            // asserts
            Assert.AreEqual(workingLinesExpected[0].Line, workingLines[0].Line);
            Assert.AreEqual(workingLinesExpected[1].Line, workingLines[1].Line);
            Assert.AreEqual(workingLinesExpected[2].Line, workingLines[2].Line);
            Assert.AreEqual(workingLinesExpected[3].Line, workingLines[3].Line);
            Assert.AreEqual(workingLinesExpected[4].Line, workingLines[4].Line);
            Assert.AreEqual(workingLinesExpected[5].Line, workingLines[5].Line);
            Assert.AreEqual(workingLinesExpected[6].Line, workingLines[6].Line);
            Assert.AreEqual(workingLinesExpected[7].Line, workingLines[7].Line);
            Assert.AreEqual(workingLinesExpected[8].Line, workingLines[8].Line);
            Assert.AreEqual(workingLinesExpected[9].Line, workingLines[9].Line);
            Assert.AreEqual(workingLinesExpected[10].Line, workingLines[10].Line);
            Assert.AreEqual(workingLinesExpected[11].Line, workingLines[11].Line);
            Assert.AreEqual(workingLinesExpected[12].Line, workingLines[12].Line);
        }

        /// <summary>
        ///A test for SA1513_ClosingCurlyBracketMustBeFollowedByBlankLine
        ///</summary>
        [TestMethod()]
        public void SA1513_ClosingCurlyBracketMustBeFollowedByBlankLineTest()
        {
            List<SFWorkingLine> workingLines = new List<SFWorkingLine>();
            saObjects = new List<SAObject>();
            saObject.ErrorId = "SA1513";
            saObjects.Add(saObject);
            List<SAObject> noViolations = new List<SAObject>();
            // no space before and after the operator
            SFWorkingLine workingLine = new SFWorkingLine(1, "\tpublic bool Enabled", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(2, "\t{", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(3, "\tget", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(4, "\t{", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(5, "\treturn this.enabled; ", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(6, "\t}", false, saObjects);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(7, "\tnevermind.MoreCode();", false, noViolations);
            workingLines.Add(workingLine);
            List<SFWorkingLine> workingLinesExpected = new List<SFWorkingLine>();
            SFWorkingLine workingLineExpected = new SFWorkingLine(1, "\tpublic bool Enabled", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(2, "\t{", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(3, "\tget", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(4, "\t{", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(5, "\treturn this.enabled; ", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(6, "\t}", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(7, "", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(8, "\tnevermind.MoreCode();", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            target.SA1513_ClosingCurlyBracketMustBeFollowedByBlankLine(ref workingLines);
            // asserts
            Assert.AreEqual(workingLinesExpected[0].Line, workingLines[0].Line);
            Assert.AreEqual(workingLinesExpected[1].Line, workingLines[1].Line);
            Assert.AreEqual(workingLinesExpected[2].Line, workingLines[2].Line);
            Assert.AreEqual(workingLinesExpected[3].Line, workingLines[3].Line);
            Assert.AreEqual(workingLinesExpected[4].Line, workingLines[4].Line);
            Assert.AreEqual(workingLinesExpected[5].Line, workingLines[5].Line);
            Assert.AreEqual(workingLinesExpected[6].Line, workingLines[6].Line);
            Assert.AreEqual(workingLinesExpected[7].Line, workingLines[7].Line);
        }

        /// <summary>
        ///A test for SA1515_SingleLineCommentMeBePreceededByABlankLine
        ///</summary>
        [TestMethod()]
        public void SA1515_SingleLineCommentMeBePreceededByABlankLineTest()
        {
            List<SFWorkingLine> workingLines = new List<SFWorkingLine>();
            saObjects = new List<SAObject>();
            saObject.ErrorId = "SA1515";
            saObjects.Add(saObject);
            List<SAObject> noViolations = new List<SAObject>();
            // no space before and after the operator
            SFWorkingLine workingLine = new SFWorkingLine(1, "\tforeach(A a in B)", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(2, "\t// comment preceeded by code", false, saObjects);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(3, "\t// comment preceeded by comment", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(4, "\t{", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(5, "\t// comment first item in scope", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(6, "\t\tDoSomething(a);", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(7, "\t//// ignored comment", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(8, "\t}", false, noViolations);
            workingLines.Add(workingLine);
            List<SFWorkingLine> workingLinesExpected = new List<SFWorkingLine>();
            SFWorkingLine workingLineExpected = new SFWorkingLine(1, "\tforeach(A a in B)", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(2, "", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(3, "\t// comment preceeded by code", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(4, "\t// comment preceeded by comment", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(5, "\t{", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(6, "\t// comment first item in scope", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(7, "\t\tDoSomething(a);", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(8, "\t//// ignored comment", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(9, "\t}", false, noViolations);            // run code
            workingLinesExpected.Add(workingLineExpected);
            target.SA1515_SingleLineCommentMeBePreceededByABlankLine(ref workingLines);
            // asserts
            Assert.AreEqual(workingLinesExpected[0].Line, workingLines[0].Line);
            Assert.AreEqual(workingLinesExpected[1].Line, workingLines[1].Line);
            Assert.AreEqual(workingLinesExpected[2].Line, workingLines[2].Line);
            Assert.AreEqual(workingLinesExpected[3].Line, workingLines[3].Line);
            Assert.AreEqual(workingLinesExpected[4].Line, workingLines[4].Line);
            Assert.AreEqual(workingLinesExpected[5].Line, workingLines[5].Line);
            Assert.AreEqual(workingLinesExpected[6].Line, workingLines[6].Line);
            Assert.AreEqual(workingLinesExpected[7].Line, workingLines[7].Line);
            Assert.AreEqual(workingLinesExpected[8].Line, workingLines[8].Line);
        }

        /// <summary>
        ///A test for SA1505_AnOpeningCurlyBracketMustNotBeFollowedByABlankLine
        ///</summary>
        [TestMethod()]
        public void SA1505_AnOpeningCurlyBracketMustNotBeFollowedByABlankLineTest()
        {
            List<SFWorkingLine> workingLines = new List<SFWorkingLine>();
            saObjects = new List<SAObject>();
            saObject.ErrorId = "SA1505";
            saObjects.Add(saObject);
            List<SAObject> noViolations = new List<SAObject>();
            // no space before and after the operator
            SFWorkingLine workingLine = new SFWorkingLine(1, "\tforeach(A a in B)", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(2, "\t{", false, saObjects);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(3, "\t", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(4, "\t\tDoSomething(a);", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(5, "\t}", false, noViolations);
            workingLines.Add(workingLine);
            List<SFWorkingLine> workingLinesExpected = new List<SFWorkingLine>();
            SFWorkingLine workingLineExpected = new SFWorkingLine(1, "\tforeach(A a in B)", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(2, "\t{", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(3, "\t\tDoSomething(a);", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(4, "\t}", false, noViolations);            // run code
            workingLinesExpected.Add(workingLineExpected);
            target.SA1505_AnOpeningCurlyBracketMustNotBeFollowedByABlankLine(ref workingLines);
            // asserts
            Assert.AreEqual(workingLinesExpected[0].Line, workingLines[0].Line);
            Assert.AreEqual(workingLinesExpected[1].Line, workingLines[1].Line);
            Assert.AreEqual(workingLinesExpected[2].Line, workingLines[2].Line);
            Assert.AreEqual(workingLinesExpected[3].Line, workingLines[3].Line);
        }

        /// <summary>
        ///A test for SA1516_ElementsMustBeSeparatedByBlankLine
        ///</summary>
        [TestMethod()]
        public void SA1516_ElementsMustBeSeparatedByBlankLineTest()
        {
            saObjects = new List<SAObject>();
            saObject.ErrorId = "SA1516";
            saObjects.Add(saObject);
            List<SAObject> noViolations = new List<SAObject>();
            List<SFWorkingLine> workingLines = new List<SFWorkingLine>();
            SFWorkingLine workingLine = new SFWorkingLine(1, "\tpublic void Method1()", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(2, "\t{", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(3, "\t}", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(4, "\tpublic bool Property", false, saObjects);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(5, "\t{", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(6, "\t    get { return true; }", false, noViolations);
            workingLines.Add(workingLine);
            workingLine = new SFWorkingLine(7, "\t}", false, noViolations);
            workingLines.Add(workingLine);
            List<SFWorkingLine> workingLinesExpected = new List<SFWorkingLine>();
            SFWorkingLine workingLineExpected = new SFWorkingLine(1, "\tpublic void Method1()", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(2, "\t{", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(3, "\t}", false, saObjects);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(4, "", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(5, "\tpublic bool Property", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(6, "\t{", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(7, "\t    get { return true; }", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            workingLineExpected = new SFWorkingLine(8, "\t}", false, noViolations);
            workingLinesExpected.Add(workingLineExpected);
            target.SA1516_ElementsMustBeSeparatedByBlankLine(ref workingLines);
            // asserts
            Assert.AreEqual(workingLinesExpected[0].Line, workingLines[0].Line);
            Assert.AreEqual(workingLinesExpected[1].Line, workingLines[1].Line);
            Assert.AreEqual(workingLinesExpected[2].Line, workingLines[2].Line);
            Assert.AreEqual(workingLinesExpected[3].Line, workingLines[3].Line);
            Assert.AreEqual(workingLinesExpected[4].Line, workingLines[4].Line);
            Assert.AreEqual(workingLinesExpected[5].Line, workingLines[5].Line);
            Assert.AreEqual(workingLinesExpected[6].Line, workingLines[6].Line);
            Assert.AreEqual(workingLinesExpected[7].Line, workingLines[7].Line);
        }
    }
}
